TRUNK-6469: Add support for automatic initialization of Envers audit tables (#5468) (#5831)#5834
TRUNK-6469: Add support for automatic initialization of Envers audit tables (#5468) (#5831)#5834wikumChamith wants to merge 1 commit intoopenmrs:2.8.xfrom
Conversation
omeriinnocent
left a comment
There was a problem hiding this comment.
The implementation of automatic Envers audit table initialization is solid:
Strengths:
- Well-structured code with proper separation of concerns in EnversAuditTableInitializer
- Comprehensive test coverage (3 main scenarios: enable/disable/custom suffix)
- Follows OpenMRS standards (license headers, naming, logging with SLF4J)
- Good error handling with APIException wrapping
- Java 8 compatible (DatabaseUtil.java fix is good)
Minor Recommendations:
-In HibernateSessionFactoryBean.generateEnversAuditTables(), consider adding a null check for hibernateProperties before passing to EnversAuditTableInitializer.initialize() for defensive programming.
-Add javadoc to the test helper method buildSessionFactoryWithEnvers() for clarity.
|
@omeriinnocent Please don't add AI-generated review comments unless they add some kind of value. While it's fine to use AI to help you identify issues that you might want to raise with a PR author in a review, just copying and pasting the AI output is unhelpful. |
| import org.hibernate.integrator.spi.Integrator; | ||
| import org.hibernate.service.ServiceRegistry; | ||
| import org.hibernate.service.spi.SessionFactoryServiceRegistry; | ||
| import org.jspecify.annotations.NonNull; |
There was a problem hiding this comment.
Prefer @Nonnull or at least the Spring version.
There was a problem hiding this comment.
This is the one used by the parent class: spring-projects/spring-framework@2691489/spring-orm/src/main/java/org/springframework/orm/jpa/hibernate/LocalSessionFactoryBean.java#L39
| */ | ||
| @Override | ||
| public void setMappingResources(String... mappingResources) { | ||
| public void setMappingResources(String @NonNull ... mappingResources) { |
There was a problem hiding this comment.
| public void setMappingResources(String @NonNull ... mappingResources) { | |
| public void setMappingResources(@Nonnull String ... mappingResources) { |
There was a problem hiding this comment.
@ibacher Since this method uses varargs, we need to annotate it as String @NonNull ..., which means the array itself cannot be null.
If we annotate it as @NonNull String ..., that means each String element cannot be null.
When I used @NonNull String ..., I got the warning:
Not annotated parameter overrides @NonNullApi parameter.
That’s why I annotated it as String @NonNull ... instead.
5b232de to
6effc2a
Compare
415fdff to
c08801a
Compare
|
| private Integer conceptReferenceRangeId; | ||
|
|
||
| @Column(name = "criteria", length = 65535) | ||
| @Column(name = "criteria", length = 255) |
There was a problem hiding this comment.
@wikumChamith, as I was also working on the same issue around and they are #5933 and #5952 and was finding this PR only where the backfill changeset only makes sense if the audit tables already exist. So, I want to point out some points that the criteria column was silently reduced from 65535 to 255 with no Liquibase migration — any existing values longer than 255 chars would be truncated on update. Was this intentional? A migration changeset is needed here.
|
|
||
| String lowerTableName = tableName.toLowerCase(); | ||
|
|
||
| if (lowerTableName.contains("revision") || lowerTableName.equals("revinfo")) { |
There was a problem hiding this comment.
@wikumChamith, Any table whose name happens to contain the word "revision" would be incorrectly pulled into the audit schema migration. This is too broad — should match only the exact Envers-generated revision table name based on the configured prefix/suffix.
| hasErrors.set(true); | ||
| log.warn("Schema migration encountered an issue: {}", throwable.getMessage()); |
There was a problem hiding this comment.
Errors during audit table creation are only logged as warnings and execution continues. If a critical table fails to create, the system starts up silently broken — this should either throw or at minimum log at ERROR level so it doesn't go unnoticed in production.
| String auditTablePrefix = hibernateProperties.getProperty("org.hibernate.envers.audit_table_prefix", ""); | ||
| String auditTableSuffix = hibernateProperties.getProperty("org.hibernate.envers.audit_table_suffix", "_audit"); | ||
|
|
||
| Map<String, Object> settings = new HashMap<>((Map) hibernateProperties); |
There was a problem hiding this comment.
This is an unchecked raw type cast that will generate a compiler warning and could throw a ClassCastException at runtime if any property value is not a String. Should use explicit population instead.
|
|
||
| @BeforeEach | ||
| void beforeEach() throws Exception { | ||
| this.dropAllDatabaseObjects(); |
There was a problem hiding this comment.
Calling dropAllDatabaseObjects() in @beforeeach means if one test fails mid-run, the DB is left in a broken state for all subsequent tests. A more targeted teardown or transaction rollback would be safer.
|
|
||
| @BeforeEach | ||
| void beforeEach() throws Exception { | ||
| this.dropAllDatabaseObjects(); |
There was a problem hiding this comment.
Calling dropAllDatabaseObjects() in @beforeeach means if one test fails mid-run, the DB is left in a broken state for all subsequent tests. A more targeted teardown or transaction rollback would be safer.
| public void integrate(Metadata metadata, SessionFactoryImplementor sessionFactory, | ||
| SessionFactoryServiceRegistry serviceRegistry) { | ||
| this.metadata = metadata; | ||
| generateEnversAuditTables(metadata, serviceRegistry); |
There was a problem hiding this comment.
Throwing APIException from inside integrate() will crash the entire SessionFactory initialization with a generic error — giving no clear signal that Envers is the cause. Should log the failure clearly and consider making it non-fatal so startup can proceed.



Description of what I changed
Cherry picked from: b276e07
Issue I worked on
see https://issues.openmrs.org/browse/TRUNK-
Checklist: I completed these to help reviewers :)
My IDE is configured to follow the code style of this project.
No? Unsure? -> configure your IDE, format the code and add the changes with
git add . && git commit --amendI have added tests to cover my changes. (If you refactored
existing code that was well tested you do not have to add tests)
No? -> write tests and add them to this commit
git add . && git commit --amendI ran
mvn clean packageright before creating this pull request andadded all formatting changes to my commit.
No? -> execute above command
All new and existing tests passed.
No? -> figure out why and add the fix to your commit. It is your responsibility to make sure your code works.
My pull request is based on the latest changes of the master branch.
No? Unsure? -> execute command
git pull --rebase upstream master